/*
 * NeuralNet.cpp
 *
 *  Created on: Sep 20, 2013
 *      Author: dennj
 */

#include "NeuralNet.h"
#include <stdlib.h>     /* srand, rand */
#include <math.h>

const unsigned HIDDEN_LAYER = 3;
const unsigned NEURON_LAYER = 4;
const unsigned FEEDBACK = 2;
const unsigned INPUT_NEURON = 3;

double input [INPUT_NEURON + 1][NEURON_LAYER];
double brain [NEURON_LAYER + 1][NEURON_LAYER][HIDDEN_LAYER];
double output [NEURON_LAYER + 1][4]; // Da aggiungere feedback

float sigmoid(float x)
{
     float exp_value;
     float return_value;

     /*** Exponential calculation ***/
     exp_value = exp((double) -x);

     /*** Final sigmoid value ***/
     return_value = 1 / (1 + exp_value);

     return return_value;
}

NeuralNet::NeuralNet() {
	// Input matrix set random
	for( int i = 0; i < INPUT_NEURON + 1; i++ )
		for( int j = 0; j < NEURON_LAYER; j++ )
			input[i][j] = (double)( rand()%1000 ) / 1000;

	// Brain set random
	for( int i = 0; i < HIDDEN_LAYER; i++ )
		for( int j = 0; j < NEURON_LAYER+1; j++ )
			for( int z = 0; z < NEURON_LAYER; z++ )
				brain[j][z][i] = (double)( rand()%1000 )/1000;

	// Output layer set random
	for( int i = 0; i < NEURON_LAYER + 1; i++ )
		for( int j = 0; j < 4; j++ )
			output[i][j] = (double)( rand()%1000 ) / 1000;
}

void NeuralNet::Think( double tmp[] ){
	//Process input with input table
	int i = 0;
	double t[ sizeof(tmp) ];
	while( i < NEURON_LAYER ){
		t[i] = 0;
		for( int j = 0; j < INPUT_NEURON + 1; j++ ){ //for every
			t[i] += tmp[ j ] * input[j][i];
		}
		i++;
	}
	for(int g=0;g<sizeof(tmp);g++)
		tmp[g] = sigmoid( t[g] );
	tmp[ i ] = 1; //bias

	// Process brain matrix
	for( i = 0; i < HIDDEN_LAYER; i++ ){
		int j = 0;
		double t[ sizeof( tmp ) ]; // vuoto?
		for(; j < NEURON_LAYER + 1; j++ ){
			t[i] = 0;
			for( int z = 0; z < NEURON_LAYER; z++ )
				t[i] += tmp[j] * brain[j][z][i];
		}
		for(int g=0;g<sizeof(tmp);g++)
			tmp[g] = sigmoid( t[g] );
		tmp[j] = 1;
	}

	t[ sizeof( tmp ) ]; // vuoto?
	i=0;
	while( i < 4){
		t[i] = 0;
		for( int j = 0; j < NEURON_LAYER + 1; j++ ){ //for every
			t[i] += tmp[ j ] * output[i][j];
		}
		i++;
	}
	for(int g=0;g<sizeof(tmp);g++)
		tmp[g] = sigmoid( t[g] );
}

double NeuralNet::Product( double a[], double b[] ){
	double tmp = 0;
	for( int i = 0; i< sizeof(a); i++)
		tmp += a[i] * b[i];
	return tmp;
}

NeuralNet::~NeuralNet() {
	// TODO Auto-generated destructor stub
}
